#! /bin/bash

# 获取环境变量
PLAY_HOME=/opt/playground

function configureContainerd() {
    # 生成默认配置文件（如果缺失）
    containerd config default | sudo tee /etc/containerd/config.toml

    # 确保配置中未禁用 CRI 插件
    if grep -q 'disabled_plugins = \["cri"\]' /etc/containerd/config.toml; then
        sed -i 's/disabled_plugins = \["cri"\]/# &/' /etc/containerd/config.toml
    fi

    # 注释掉 disabled_plugins = [] 行
    if grep -q 'disabled_plugins = \[\]' /etc/containerd/config.toml; then
        sed -i 's/disabled_plugins = \[\]/# &/' /etc/containerd/config.toml
    fi

    # 修改 registry 配置中的 config_path
    sudo sed -i '/\[plugins."io.containerd.grpc.v1.cri".registry\]/,+1 {
        s|config_path = ""|config_path = "/etc/containerd/certs.d"|
    }' /etc/containerd/config.toml

    # 设置 SystemdCgroup = true
    if grep -q "SystemdCgroup" /etc/containerd/config.toml; then
        sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
    else
        sudo sed -i '/\[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options\]/a \
        \ \ SystemdCgroup = true' /etc/containerd/config.toml
    fi

    # 创建镜像加速配置目录和文件
    sudo mkdir -p /etc/containerd/certs.d/docker.io
    cat > /etc/containerd/certs.d/docker.io/hosts.toml << EOF
server = "https://docker.io"
[host."https://docker.1ms.run"]
  capabilities = ["pull", "resolve"]
[host."https://registry.cn-hangzhou.aliyuncs.com"]
  capabilities = ["pull", "resolve"]
EOF

    mkdir -p /etc/containerd/certs.d/registry.k8s.io
    cat > /etc/containerd/certs.d/registry.k8s.io/hosts.toml << EOF
server = "https://registry.k8s.io"
[host."https://registry.aliyuncs.com/google_containers"]
  capabilities = ["pull", "resolve"]
EOF
    # 创建 /etc/crictl.yaml 文件
    cat <<EOF | sudo tee /etc/crictl.yaml
runtime-endpoint: unix:///var/run/containerd/containerd.sock
image-endpoint: unix:///var/run/containerd/containerd.sock
timeout: 10
debug: false
EOF

    # 手动设置 bridge-nf-call-iptables 参数
    echo 1 | sudo tee /proc/sys/net/bridge/bridge-nf-call-iptables

    # 重启 containerd
    systemctl restart containerd
    echo "containerd 服务已重启并配置完成"
}

function installCalicoImages() {
    # 下载 Calico 镜像
    echo "正在下载 Calico 镜像..."
    docker pull calico/cni:v3.25.0
    docker pull calico/node:v3.25.0
    docker pull calico/kube-controllers:v3.25.0

    # 保存镜像到 tar 文件
    docker save -o calico-cni-v3.25.0.tar calico/cni:v3.25.0
    docker save -o calico-node-v3.25.0.tar calico/node:v3.25.0
    docker save -o calico-kube-controllers-v3.25.0.tar calico/kube-controllers:v3.25.0

    # 使用 containerd 导入镜像到 k8s.io 命名空间
    ctr -n k8s.io images import calico-cni-v3.25.0.tar
    ctr -n k8s.io images import calico-node-v3.25.0.tar
    ctr -n k8s.io images import calico-kube-controllers-v3.25.0.tar

    echo "Calico 镜像已下载并导入"
}

function installK8s()
{
    #1.在frames.txt中查看是否需要安装k8s
    k8sInfo=`egrep "^k8s" $PLAY_HOME/frames.txt`

    k8s=`echo $k8sInfo | cut -d " " -f1`
    isInstall=`echo $k8sInfo | cut -d " " -f2`
    k8sNodes=`echo $k8sInfo | cut -d " " -f3` 
    masterNode=`echo $k8sInfo | cut -d " " -f4` 
    node=`hostname`

    masterInfo=`egrep "$masterNode" $PLAY_HOME/host_ip.txt`
    masterIP=`echo $masterInfo | cut -d " " -f1`

    # 默认K8s版本
    k8s_version="v1.20.0"
    
    # 提示用户选择K8s版本
    echo "请选择要安装的K8s版本:"
    echo "1. v1.20.0 (默认)"
    echo "2. v1.20.1"
    echo "3. v1.27.2"
    read -p "请输入选择 (1/2/3): " version_choice
    
    case $version_choice in
      2)
        k8s_version="v1.20.1"
        echo "已选择安装K8s版本: $k8s_version"
        ;;
      3)
        k8s_version="v1.27.2"
        echo "已选择安装K8s版本: $k8s_version"
        ;;
      *)
        echo "已选择默认K8s版本: $k8s_version"
        ;;
    esac

    #是否安装
    if [[ $isInstall = "true" && $masterNode = $node ]];then
        
        #2.查看/opt/frames目录下是否有k8s安装包
        k8sIsExists=`find $PLAY_HOME/frames -name $k8s`

        if [[ ${#k8sIsExists} -ne 0 ]];then

            # 离线方式安装
            echo "离线方式安装"

        else
            echo "$PLAY_HOME/frames目录下没有k8s安装包，开始在线安装"
            #遍历配置安装节点
            OLD_IFS="$IFS" #保存旧的分隔符
            IFS=","
            nodes=($k8sNodes)
            IFS="$OLD_IFS" # 将IFS恢复成原来的
            for i in "${!nodes[@]}"; do
                # 循环初始化k8s环境，传递版本参数
                ssh -n ${nodes[i]} "$PLAY_HOME/systems/preK8sConfig.sh $k8s_version"
            done

            # 如果是1.27.2版本，配置containerd
            if [[ $k8s_version == "v1.27.2" ]]; then
                for i in "${!nodes[@]}"; do
                    ssh -n ${nodes[i]} "$(declare -f configureContainerd); configureContainerd"
                done
            fi
        
            # 根据版本选择是否添加 --cri-socket 参数
            if [[ $k8s_version == "v1.27.2" ]]; then
                cri_socket="--cri-socket unix:///var/run/containerd/containerd.sock"
            else
                cri_socket=""
            fi

            # 使用适当的 cri-socket 初始化 Kubernetes
            kubeadm init --kubernetes-version=$k8s_version --pod-network-cidr=10.244.0.0/16 --service-cidr=10.96.0.0/12 --apiserver-advertise-address $masterIP $cri_socket > /tmp/k8s.tmp
            
            mkdir -p $HOME/.kube
            sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
            sudo chown $(id -u):$(id -g) $HOME/.kube/config

            slave_str=`tail -n 2 /tmp/k8s.tmp`
            slave_join=`echo $slave_str | sed 's/\\\//g'`
            for i in "${!nodes[@]}"; do
                if [[ ${nodes[i]} != $masterNode ]];then
                # 添加slave节点
                ssh -n ${nodes[i]} $slave_join
                # 拷贝配置文件到slave节点
                scp /etc/kubernetes/admin.conf root@${nodes[i]}:`pwd`
                # 执行初始化
                ssh -n ${nodes[i]} "mkdir -p \$HOME/.kube"
                # ssh -n ${nodes[i]} "cp -i /etc/kubernetes/admin.conf \$HOME/.kube/config"
                scp /etc/kubernetes/admin.conf root@${nodes[i]}:$HOME/.kube/config
                ssh -n ${nodes[i]} "chown $(id -u):$(id -g) \$HOME/.kube/config"
                fi
            done

            # 安装网络插件
            echo "请选择要安装的网络插件:"
            echo "1. Flannel (默认)"
            echo "2. Calico"
            read -p "请输入选择 (1/2): " network_choice

            case $network_choice in
              2)
                echo "已选择安装Calico"
                # 在每个节点上安装 Calico 镜像
                for i in "${!nodes[@]}"; do
                    ssh -n ${nodes[i]} "$(declare -f installCalicoImages); installCalicoImages"
                done
                # 安装Calico
                calicoIsExists=`find $PLAY_HOME/frames -name calico.yaml`
                if [[ ${#calicoIsExists} -ne 0 ]];then
                    # 直接离线安装
                    kubectl apply -f $PLAY_HOME/frames/calico.yaml
                else
                    # 在线安装
                    kubectl apply -f https://docs.projectcalico.org/manifests/calico.yaml
                fi
                ;;
              *)
                echo "已选择安装Flannel"
                # 安装Flannel
                flannelIsExists=`find $PLAY_HOME/frames -name kube-flannel.yaml`
                if [[ ${#flannelIsExists} -ne 0 ]];then
                    # 直接离线安装
                    kubectl apply -f $PLAY_HOME/frames/kube-flannel.yaml
                else
                    # 在线安装
                    kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
                fi
                ;;
            esac

            # 创建Flannel CNI配置，防止节点处于NotReady状态
            if [[ $network_choice -eq 1 ]]; then
                for i in "${!nodes[@]}"; do
                    ssh -n ${nodes[i]} "cat <<EOF | sudo tee /etc/cni/net.d/10-flannel.conflist
{
  \"name\": \"cbr0\",
  \"cniVersion\": \"0.3.1\",
  \"plugins\": [
    {
      \"type\": \"bridge\",
      \"name\": \"cbr0\",
      \"ipMasq\": true,
      \"isGateway\": true,
      \"ipam\": {
        \"type\": \"host-local\",
        \"subnet\": \"10.244.0.0/16\",
        \"routes\": [
          { \"dst\": \"0.0.0.0/0\" }
        ]
      }
    },
    {
      \"type\": \"portmap\",
      \"capabilities\": {
        \"portMappings\": true
      }
    }
  ]
}
EOF"
                done
                echo "Flannel CNI配置已创建，等待节点就绪..."
            fi
            
        fi
    else
        echo "K8S需要在主节点进行安装，请检查配置文件！"
    fi
}

installK8s
